package com.ksyun.campus.metaserver.controller;

import com.ksyun.campus.metaserver.domain.dto.ApiResponse;
import com.ksyun.campus.metaserver.services.LeaderElectionService;
import com.ksyun.campus.metaserver.services.MetadataSyncService;
import com.ksyun.campus.metaserver.storage.MetadataStore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 管理接口控制器
 * 提供集群管理、数据一致性检查和修复功能
 */
@Slf4j
@RestController
@RequestMapping("/admin")
public class AdminController {
    
    @Autowired
    private MetadataSyncService syncService;
    
    @Autowired
    private LeaderElectionService leaderElection;
    
    @Autowired
    private MetadataStore metadataStore;
    
    /**
     * 获取当前节点的数据摘要
     * 用于数据一致性检查
     */
    @GetMapping("/data-summary")
    public ApiResponse<MetadataSyncService.DataSummary> getDataSummary() {
        try {
            MetadataSyncService.DataSummary summary = new MetadataSyncService.DataSummary();
            summary.totalInodes = metadataStore.getTotalInodeCount();
            summary.totalBlocks = metadataStore.getTotalBlockCount();
            
            // 计算简单的校验和
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            md.update(String.valueOf(summary.totalInodes).getBytes());
            md.update(String.valueOf(summary.totalBlocks).getBytes());
            
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            summary.checksum = sb.toString();
            
            return ApiResponse.success(summary);
        } catch (Exception e) {
            log.error("获取数据摘要失败", e);
            return ApiResponse.error("获取数据摘要失败: " + e.getMessage());
        }
    }
    
    /**
     * 执行全集群数据一致性检查
     * 只有Leader节点可以执行此操作
     */
    @PostMapping("/consistency-check")
    public ApiResponse<MetadataSyncService.ConsistencyCheckResult> performConsistencyCheck() {
        try {
            if (!leaderElection.isLeader()) {
                return ApiResponse.error("只有Leader节点可以执行一致性检查");
            }
            
            MetadataSyncService.ConsistencyCheckResult result = syncService.performConsistencyCheck();
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("执行一致性检查失败", e);
            return ApiResponse.error("执行一致性检查失败: " + e.getMessage());
        }
    }
    
    /**
     * 重置从节点数据
     * 当从节点数据比主节点多时使用
     */
    @PostMapping("/reset-follower/{followerId}")
    public ApiResponse<Map<String, Object>> resetFollowerData(@PathVariable String followerId) {
        try {
            if (!leaderElection.isLeader()) {
                return ApiResponse.error("只有Leader节点可以执行从节点重置");
            }
            
            boolean success = syncService.resetFollowerData(followerId);
            
            Map<String, Object> result = new HashMap<>();
            result.put("followerId", followerId);
            result.put("success", success);
            result.put("message", success ? "从节点重置成功" : "从节点重置失败");
            
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("重置从节点数据失败", e);
            return ApiResponse.error("重置从节点数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 重置本节点数据（从节点调用）
     * 清空所有元数据，准备重新同步
     */
    @PostMapping("/reset-data")
    public ApiResponse<Map<String, Object>> resetLocalData() {
        try {
            if (leaderElection.isLeader()) {
                return ApiResponse.error("Leader节点不能重置自己的数据");
            }
            
            log.warn("收到数据重置请求，准备清空所有元数据");
            
            // 清空所有元数据
            metadataStore.clearAllData();
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("message", "本节点数据已重置，等待重新同步");
            
            log.info("本节点数据重置完成");
            return ApiResponse.success(result);
            
        } catch (Exception e) {
            log.error("重置本节点数据失败", e);
            return ApiResponse.error("重置本节点数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取集群同步状态
     */
    @GetMapping("/sync-status")
    public ApiResponse<Map<String, Object>> getSyncStatus() {
        try {
            Map<String, Object> status = new HashMap<>();
            status.put("currentNode", syncService.getCurrentSyncStatus());
            status.put("isLeader", leaderElection.isLeader());
            
            if (leaderElection.isLeader()) {
                status.put("followers", syncService.getAllFollowerSyncStatus());
            }
            
            return ApiResponse.success(status);
        } catch (Exception e) {
            log.error("获取同步状态失败", e);
            return ApiResponse.error("获取同步状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取节点健康状态
     */
    @GetMapping("/health")
    public ApiResponse<Map<String, Object>> getHealth() {
        try {
            Map<String, Object> health = new HashMap<>();
            health.put("status", "UP");
            health.put("isLeader", leaderElection.isLeader());
            health.put("instanceId", leaderElection.getCurrentInstance().getInstanceId());
            health.put("totalInodes", metadataStore.getTotalInodeCount());
            health.put("totalBlocks", metadataStore.getTotalBlockCount());
            
            return ApiResponse.success(health);
        } catch (Exception e) {
            log.error("获取健康状态失败", e);
            return ApiResponse.error("获取健康状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 手动触发数据同步（从节点调用）
     */
    @PostMapping("/trigger-sync")
    public ApiResponse<Map<String, Object>> triggerSync() {
        try {
            if (leaderElection.isLeader()) {
                return ApiResponse.error("Leader节点不需要触发同步");
            }
            
            // 这里可以添加手动触发同步的逻辑
            Map<String, Object> result = new HashMap<>();
            result.put("message", "同步触发请求已提交");
            
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("触发同步失败", e);
            return ApiResponse.error("触发同步失败: " + e.getMessage());
        }
    }
}